# -*- coding: utf-8 -*-
# @version : 1.0
# @File    : main.py
# @Date    : 2024/9/13 09:20
# @Author  : GlenZhao
# @Desc    : 主程序入口
import asyncio
from fastapi import FastAPI
import uvicorn
from starlette.middleware.cors import CORSMiddleware
from starlette.staticfiles import StaticFiles
import typer

from application import settings, urls
from core.docs import custom_api_docs
from utils.tools import import_modules
from core.exception import register_exception
from core.events import lifespan

shell_app = typer.Typer()

"""
command:
python main.py 启动服务
"""

def create_app():
    """启动项目"""
    app = FastAPI(
        title="RPA",
        description="RPA Pro",
        version=settings.VERSION,
        lifespan=lifespan,
        docs_url=None,
        redoc_url=None
    )
    import_modules(settings.MIDDLEWARES, "中间件", app=app)
    # 全局异常捕捉处理
    register_exception(app)
    # 跨域解决
    if settings.CORS_ORIGIN_ENABLE:
        app.add_middleware(
            CORSMiddleware,
            allow_origins=settings.ALLOW_ORIGINS,
            allow_credentials=settings.ALLOW_CREDENTIALS,
            allow_methods=settings.ALLOW_METHODS,
            allow_headers=settings.ALLOW_HEADERS
        )
    # 挂在静态目录
    if settings.STATIC_ENABLE:
        app.mount(settings.STATIC_URL, app=StaticFiles(directory=settings.STATIC_ROOT))
    # 挂载upload目录
    if settings.UPLOAD_ENABLE:
        app.mount(settings.UPLOAD_URL, app=StaticFiles(directory=settings.UPLOAD_ROOT))
    # 引入应用中的路由
    for url in urls.urlpatterns:
        app.include_router(url["ApiRouter"], prefix=url["prefix"], tags=url["tags"])
    # 配置接口文档静态资源
    custom_api_docs(app)
    
    return app

@shell_app.command()
def run(
    host: str = typer.Option(default=settings.SERVER_ADDRESS, help='监听主机IP，默认开放给本网络所有主机'),
    port: int = typer.Option(default=settings.SERVER_PORT, help='监听端口')
):
    """
    启动项目

    factory: 在使用 uvicorn.run() 启动 ASGI 应用程序时，可以通过设置 factory 参数来指定应用程序工厂。
    应用程序工厂是一个返回 ASGI 应用程序实例的可调用对象，它可以在启动时动态创建应用程序实例。
    """
    uvicorn.run(app='main:create_app', host=host, port=port, lifespan="on", factory=True)

if __name__ == '__main__':
    shell_app()